#ifndef __HERMITE__
#define __HERMITE__

#include <iostream>
#include <vector>
#include "Function.h"

//这个头文件的含义是对每个样条区间有了四个相应的插值，即x_i,x_i',x_i+1,x_(i+1)'后进行，该类最终生成相应的分段函数；
class Hermite {
//公共函数，其中主要部分就是进行Hermite插值
public:
    Hermite(const std::vector<double>& _x, const std::vector<std::vector<double>>& _y) : 
        n(_x.size() - 1), x(_x), y(_y) {

        diff_table.resize(n + 1);
        // 对插值表的第一列进行初始化
        for (int i = 0; i <= n; i++) {
            diff_table[i].resize(n + 1);
            diff_table[i][0] = y[0][i];
        }
        // 生成插值表
        for (int j = 1; j <= n; j++) {
            for (int i = j; i <= n; i++) {
                // =当用到x导数情况
                if (x[i] == x[i - j]) {
                    double res = 1;
                    for (int k = 1; k <= j; k++) {
                        res *= k;
                    }
                    diff_table[i][j] = y[j][i] / res;
                } else {
                    diff_table[i][j] = 1.0 * (diff_table[i][j - 1] - diff_table[i - 1][j - 1]) / (x[i] - x[i - j]);
                }
            }
        }
    }
    //定义相关运算。
    double operator()(const double &point) const {
        double res = 0, x_degree = 1;
        for (int i = 0; i <= x.size() - 1; i++) {
            res += diff_table[i][i] * x_degree;
            x_degree *= (point - x[i]);
        }
        return res;
    };
    //得到这个多项式，这一步也是声明这个类的目的
    Polynomial get_poly() const {
        Polynomial res(0), poly(1);
        for (int i = 0; i <= x.size() - 1; i++) {
            res = res + poly * diff_table[i][i];
            poly = poly * Polynomial(-x[i], 1);
        }
        return res;
    };
//私有类包括插值个数，在本次作业中基本应用为4，x为上述描述，y为插值，声明差分表的原因为差分表可以储存上一步的插值
private:
    int n;
    std::vector<double> x;
    std::vector<std::vector<double>> y;
    std::vector<std::vector<double>> diff_table;
};

#endif
